use std::collections::HashMap;
use mysql::Value;
use crate::rules::Vo;
use crate::util::{db, cap};

// 保存日志信息
pub fn save_log(map: &HashMap<String, Value>) -> u32 {
    db::save("log_info", map)
}

// 查询附件信息
pub fn get_attachment(cols: &str, parent_id: &u32, parent_type: &str) -> Vo {
    let vec = attachment_list(cols, parent_id, parent_type);
    if vec.is_empty() {
        Vo{data: HashMap::new()}
    } else {
        vec.get(0).unwrap().to_owned()
    }
}

// 查询附件列表
pub fn attachment_list(cols: &str, parent_id: &u32, parent_type: &str) -> Vec<Vo> {
    let sql = format!("select {} from attachment where parentId=? and parentType=?", cols);
    let paras = vec![Value::from(parent_id), Value::from(parent_type)];
    
    db::list(&sql, &paras)
}

// 保存附件信息
pub fn save_attachment(parent_id: &u32, path: &str) {
    let attach = get_attachment("id", parent_id, "users");
    if attach.empty() {
        let map = map!{
            "path" => Value::from(path),
            "parentId" => Value::from(parent_id),
            "parentType" => Value::from("users")
        };
        db::save("attachment", &map);
    } else {
        let map = map!{
            "id" => Value::from(attach.long("id")),
            "path" => Value::from(path)
        };
        let _ = db::update("attachment", &map);
    }
}

// 查询字典信息
pub fn get_dictionary(parent_name: &str) -> Vec<Vo> {
    let sql = "select d2.name from dictionary d1 inner join dictionary d2 on d1.name=? and d1.id=d2.parentId";
    let paras = vec![Value::from(parent_name)];
    
    db::list(&sql, &paras)
}

// 查询部门列表
pub fn department_list(cols: &str, vo: &Vo) -> Vec<Vo> {
    let len = vo.len();
    let mut paras = Vec::with_capacity(len);
    let mut sql = String::with_capacity(cap(len));
    sql.push_str(&format!("select {} from department", cols));
    if len > 0 {
        if vo.not_blank("name") {
            sql.push_str(" where name like ?");
            paras.push(Value::from(format!("{}%", vo.str("name"))));
        }
        if vo.not_blank("page") {
            let size = vo.int("size");
            sql.push_str(" limit ");
            sql.push_str(&format!("{}", (vo.int("page") - 1) * size));
            sql.push(',');
            sql.push_str(&format!("{}", size));
        }
    }
    
    db::list(&sql, &paras)
}

// 查询菜单列表
pub fn menu_list() -> Vec<Vo> {
    let sql = "select id,name,url,orders,parentId,types from menu order by orders";
    
    db::list(&sql, &[])
}

// 查询用户拥有的菜单ID
pub fn user_menus(user_id: u32) -> Vec<Vo> {
    let sql = "select menuId from users_menu where userId=?";
    let paras = vec![Value::from(user_id)];
    
    db::list(&sql, &paras)
}

// 保存用户菜单权限
pub fn save_user_menus(vo: &Vo) {
    if vo.bool("checked") {
        let menu_id = vo.str("menuId");
        let mut ids: Vec<&str> = menu_id.split(',').collect();
        let mut sql = String::with_capacity(cap(vo.len()));
        sql.push_str("select menuId from users_menu where userId=");
        sql.push_str(vo.str("parentId"));
        sql.push_str(" and menuId in (");
        sql.push_str(menu_id);
        sql.push_str(") group by menuId");
        let list = db::list(&sql, &[]);
        //删除已在数据库中添加过的权限
        ids.retain(|id| {
            for vo in list.iter() {
                if id == &(vo.str("menuId")) {
                    return false;
                }
            }
            true
        });
        let user_id = vo.long("parentId");
        let mut paras = Vec::<Vec<Value>>::with_capacity(ids.len());
        for id in ids.iter() {
            paras.push(vec![Value::from(user_id), Value::from(id.parse::<u32>().unwrap())]);
        }
        let sql = "insert into users_menu(userId, menuId) values (?, ?)";
        let _ = db::batch(&sql, &paras);
    } else {
        let list: Vec<&str> = vo.str("menuId").split(',').collect();
        let user_id = vo.long("parentId");
        let mut paras = Vec::<Vec<Value>>::with_capacity(list.len());
        for menu_id in list.iter() {
            paras.push(vec![Value::from(user_id), Value::from(menu_id.parse::<u32>().unwrap())]);
        }
        let sql = "delete from users_menu where userId=? and menuId=?";
        let _ = db::batch(&sql, &paras);
    }
}

// 查询车次列表
pub fn train_list(cols: &str, vo: &Vo) -> Vec<Vo> {
    let len = vo.len();
    let mut paras = Vec::with_capacity(len);
    let mut sql = String::with_capacity(cap(len));
    sql.push_str(&format!("select {} from train", cols));
    if len > 0 {
        sql.push_str(" where 1=1");
        if vo.not_blank("team") {
            sql.push_str(" and team=?");
            paras.push(Value::from(vo.str("team")));
        }
        if vo.not_blank("name") {
            sql.push_str(" and name like ?");
            paras.push(Value::from(format!("{}%", vo.str("name"))));
        }
        if vo.not_blank("statu") {
            sql.push_str(" and statu=?");
            paras.push(Value::from(vo.int("statu")));
        }
        if vo.not_blank("orderBy") {
            sql.push_str(" order by ");
            sql.push_str(vo.str("orderBy"));
        }
        if vo.not_blank("page") {
            let size = vo.int("size");
            sql.push_str(" limit ");
            sql.push_str(&format!("{}", (vo.int("page") - 1) * size));
            sql.push(',');
            sql.push_str(&format!("{}", size));
        }
    }
    
    db::list(&sql, &paras)
}
